﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;


namespace QQZiFramework
{
    public class QueryEntityInstance
    {




        public QueryEntityConfig Config { get; set; }

        /// <summary>
        /// 主键信息
        /// </summary>
        public CustomerProperty PrimarkKey
        {
            get
            {
                return Param.LoaderInfo.PrimaryCusPro;
            }
        }

        public QueryParam Param { get; set; }
        public bool Lock { get; internal set; }

        /// <summary>
        /// 获取查询实体的表定义
        /// </summary>
        /// <returns></returns>
        public DBTableAttribute GetTableAttr()
        {
            return DBContext.GET_TABLE_ATTR_STATIC(Param.entityType);
        }

        /// <summary>
        /// 本次查询中所有的表对应的另名
        /// </summary>
        private Dictionary<string, string> tableAlias;

        /// <summary>
        /// 获取表的别名
        /// </summary>
        /// <param name="table"></param>
        /// <param name="qEntity"></param>
        /// <returns></returns>
        public string GetTableAliasName(string table)
        {
            if (tableAlias == null) tableAlias = new Dictionary<string, string>();
            string alias;
            if (tableAlias.TryGetValue(table, out alias)) return alias;
            if (Config.TableSql == null) return string.Empty;
            if (table == null) throw new ClientException("GetTableAliasName must have a parameter with value(table)");
            int pos = Config.TableSql.IndexOf(table, StringComparison.OrdinalIgnoreCase);
            if (pos == -1) throw new ClientException(table + "没定义在TableSql中");
            pos += table.Length + 1;
            if (Config.TableSql.Length <= pos)
            {
                tableAlias.Add(table, Config.TableSql);
                return Config.TableSql;
            }
            int i = pos;
            while (i < Config.TableSql.Length && Config.TableSql[i] == ' ') { i++; }//跳过空格，找下个非空字符
            int aliasStartIndex;
            int j = i + 1;
            if (j > Config.TableSql.Length) throw new Exception("TableSql中的别名配置有误！");
            if ((Config.TableSql[i] == 'a' || Config.TableSql[i] == 'A') && (Config.TableSql.Length > j && (Config.TableSql[j] == 's' || Config.TableSql[j] == 'S')))
                aliasStartIndex = j + 1;  //找到as
            else
                aliasStartIndex = i;    //没有as直接就是接下来的别名
            while (aliasStartIndex < Config.TableSql.Length && Config.TableSql[aliasStartIndex] == ' ') aliasStartIndex++;//路过空格，计算别名位置
            if (aliasStartIndex >= Config.TableSql.Length) throw new Exception("TableSql中的别名配置有误！");
            int aliasEndIndex = aliasStartIndex;
            while (aliasEndIndex < Config.TableSql.Length && Config.TableSql[aliasEndIndex] != ' ') aliasEndIndex++;
            aliasEndIndex--;
            return Config.TableSql.Substring(aliasStartIndex, aliasEndIndex - aliasStartIndex + 1);
        }

        public string CreateWhereItemParameters(string whereKey, IWhereItem whereItem, DBContext context, out IDbDataParameter[] itemParameters)
        {
            string[] configArr;
            this.Config.Fields.TryGetValue(whereKey, out configArr); //查找查询条件表达式的配置，没有则使用客户端
            if (configArr != null) configArr = configArr.Clone() as string[]; //后面会修改数组的值，这里用copy                

            // if (queryInstance.Param.StrictModel.Value)
            // {
            //     Utility.CheckSqlXSS(ki.Value);
            // }
            string dbFieldName = null;
            bool hasWhereConfig = configArr != null && configArr.Length > 1 && !string.IsNullOrEmpty(configArr[1]);
            if (hasWhereConfig)
            {
                if (configArr[1].StartsWith("$concat_template")) whereItem.ConcatTemplate = configArr[1].Substring(17);
                else
                {
                    var customerWhereItem = whereItem as WhereItem_Custom;
                    if (customerWhereItem != null)
                    {
                        //如果Permission文件里面有配置where表达式，则使用
                        customerWhereItem.SetWhenPermissionHasConfig(context, configArr[1]);
                    }
                    else
                    {
                        context.LogDebug(whereKey + "不是WhereItem_Custom类型，不使用Permission的定义");
                        // throw new Exception(whereKey + "已经在Permission中定义，请使用WhereItem_Eq，而不是" + whereItem.GetType().Name);
                    }
                }
            }
            else
            {
                if (whereKey.IndexOf('.') > -1)
                {
                    //客户端where直接添加的表前缀,比如a.id
                    dbFieldName = whereKey;
                }
            }
            if (dbFieldName == null)
            {
                var fieldCp = this.Param.LoaderInfo.GetCustomerProperty(whereKey);
                if (fieldCp != null) dbFieldName = context.GetDbField(this, fieldCp, 0, this.GetTableAttr());
                else
                {
                    //如果找不到列名,使用permission里的字段配置
                    if (configArr != null && configArr.Length > 0 ) {
                        dbFieldName = configArr.Length >2?configArr[2]:configArr[0];//如果有定义order的表达式，使用order的，否者用select的。
                    }
                    else throw new ClientException("查询条件表达式错误：" + this.Param.entityType.Name + "并不包含" + whereKey);
                }
            }
            return whereItem.ParseSql(context, whereKey, dbFieldName, out itemParameters);
        }

    }

    public class Pagger
    {
        public int PageSize;
        /// <summary>
        /// 页码,从1开始
        /// </summary>
        public int PageIndex;

        /// <summary>
        /// 总记录数，仅在第一页查询时返回
        /// </summary>
        public int Total;

        /// <summary>
        /// 除Count外的汇总项字典,比如sum(其它字段),需要对应Permission字段配置
        /// </summary>
        public Dictionary<string, object> GroupByDic;

        /// <summary>
        /// 添加分页查询的汇总字段,需要对应Permission字段配置
        /// </summary>
        /// <param name="fields"></param>
        public void SetGroupByFields(string fields)
        {
            if (fields == null) return;
            if (GroupByDic == null) GroupByDic = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            foreach (string field in fields.Split(','))
            {
                GroupByDic.Add(field, null);
            }
        }

    }

    /// <summary>
    /// 查询实体，比如：{table:[t1,t2] ,fields:{name:[""a.name"", ""a.name like '{0}' ""]},page:{pageSize:2,pageIndex:1}}
    /// </summary>
    public class QueryEntityConfig
    {

        public QueryEntityConfig() { NotAllowDelete = true; }

        public bool RequreLogin { get; set; }

        public bool RequreAdmin { get; set; }

        public bool RequerSelf { get; set; }

        public bool RequerNotSelf { get; set; }

        /// <summary>
        /// 默认会加的where条件。客户端发上来的请求查询，默认生效，后台手动生产
        /// </summary>
        public Dictionary<string, string> Defaults;

        /// <summary>
        /// 不允许查询的列的集合
        /// </summary>
        public string[] NotAllowQuery { get; set; }

        /// <summary>
        /// 不允许查询的列的集合
        /// </summary>
        public string[] NotAllowSaving { get; set; }

        /// <summary>
        /// 不允许查询的列的集合
        /// </summary>        
        public bool NotAllowDelete { get; set; }

        /// <summary>
        /// 就算是空值也会更新的列的集合
        /// </summary>
        public string[] IgnoreNull { get; set; }

        private Dictionary<string, string[]> mFields;

        /// <summary>
        /// 集合：列的配置，每项为数组[select表达式,where表达式,orderby表达式]
        /// </summary>
        public Dictionary<string, string[]> Fields
        {
            get
            {
                return mFields;
            }
            set
            {
                mFields = value;
                if (mFields != null)
                {
                    foreach (string key in mFields.Keys.ToArray())
                    {
                        var arr = mFields[key];
                        if (arr != null)
                        {
                            for (int i = 0; i < arr.Length; i++)
                            {
                                if (arr[i] != null) arr[i] = arr[i].Replace("$field", "${field}");
                            }
                        }
                    }
                }
            }
        }


        public string[] Items { get; set; }

        public QueryEntityConfig[] QItems { get; set; }

        public string TableSql { get; set; }

        /// <summary>
        /// 创建与实体同名的配置，在末配置的时候使用
        /// </summary>
        /// <param name="entityType"></param>
        /// <param name="queryEntity"></param>
        /// <param name="permission"></param>
        /// <returns></returns>
        public static QueryEntityConfig Create(string permission)
        {
            QueryEntityConfig qe = new QueryEntityConfig();
            qe.Fields = new Dictionary<string, string[]>();
            //foreach (KeyValuePair<string, string> ki in queryEntity)
            //{
            //    string[] queryValArr = ki.Value.Split(',');
            //    if (queryValArr.Length > 1)
            //        qe.Fields.Add(ki.Key, new string[] { ki.Key, ki.Key + " between '{0}' and '{1}'" });
            //    else
            //        qe.Fields.Add(ki.Key, new string[] { ki.Key, ki.Key + " = '{0}'" });
            //}            
            return qe;
        }



    }

    public class ExecEntity
    {
        public String table;
        public DBAction action;
        public String[] fields;
        public String[] values;
        public String where;
    }
    public enum DBAction { Add = 0, Delete = 2, Update = 1 }

}
